package read

import (
	"fmt"
	"reflect"
)

// ReadHaveValueTag 读标签 获取val结构体参数数据
// 仅返回数据非空的字段数据及对应字段结构
func ReadHaveValueTag(val interface{}, tag string) ([]string, []interface{}) {
	columns := make([]string, 0)
	params := make([]interface{}, 0)

	typeOf := reflect.TypeOf(val)
	valueOf := reflect.ValueOf(val)

	for i := 0; i < typeOf.NumField(); i++ {
		column := typeOf.Field(i).Tag.Get(tag)
		value := valueOf.Field(i).Interface()
		if !ValueIsBlank(reflect.ValueOf(value)) {
			columns = append(columns, column)
			params = append(params, value)
		}
	}
	return columns, params
}

// ReadAllTag 读标签 获取val结构体参数数据
// 返回所有的字段数据及对应字段结构
func ReadAllTag(val interface{}, tag string) ([]string, []interface{}) {
	columns := make([]string, 0)
	params := make([]interface{}, 0)

	typeOf := reflect.TypeOf(val)
	valueOf := reflect.ValueOf(val)

	for i := 0; i < typeOf.NumField(); i++ {
		column := typeOf.Field(i).Tag.Get(tag)
		value := valueOf.Field(i).Interface()
		if column != "" {
			columns = append(columns, column)
			if !ValueIsBlank(reflect.ValueOf(value)) {
				params = append(params, value)
			} else {
				params = append(params, nil)
			}
		}
	}
	return columns, params
}

// ValueIsBlank reflect.Value结构体方法封装
// 判断当前结构参数数据是否为空
func ValueIsBlank(value reflect.Value) bool {
	switch value.Kind() {
	case reflect.String:
		return value.Len() == 0
	case reflect.Bool:
		return !value.Bool()
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		return value.Int() == 0
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
		return value.Uint() == 0
	case reflect.Float32, reflect.Float64:
		return value.Float() == 0
	case reflect.Interface, reflect.Ptr:
		return value.IsNil()
	}
	return reflect.DeepEqual(value.Interface(), reflect.Zero(value.Type()).Interface())
}

// IsZero 判断当前结果为零值
func IsZero(val interface{}) bool {
	return nil == val || reflect.Zero(reflect.TypeOf(val)) == val
}

// TypeEquals 判断两个结果类型是否一致
func TypeEquals(vals ...interface{}) bool {
	for i := range vals {
		if i > 0 && reflect.TypeOf(vals[i-1]) != reflect.TypeOf(vals[i]) {
			return false
		}
	}
	return true
}

// InterfaceToSlice slice interface转interface[]
func InterfaceToSlice(slice interface{}) ([]interface{}, error) {
	result := make([]interface{}, 0)
	switch reflect.TypeOf(slice).Kind() {
	case reflect.Slice, reflect.Array:
		vals := reflect.ValueOf(slice)
		for i := 0; i < vals.Len(); i++ {
			result = append(result, vals.Index(i).Interface())
		}
	default:
		return nil, fmt.Errorf("slice type error")
	}
	return result, nil
}
